/**
 * N*M的方阵，从左上走到右下，只能向右或者向下
 * 问最少添加几个障碍物，使得走不通
 * 答案最多是2，直接把起点堵住即可。
 * 答案为0也很容易判断。因此只需要判断答案是否为1的情况
 * 如果存在必经点，答案就为1。
 * 令Dij为起点到ij的不同路径的数量，Uij为ij到终点的数量
 * 如果 Dij * Uij == D[N][M] 说明ij是必经点
 * 用双哈希
 */
#include <bits/stdc++.h>
using namespace std;

#include <bits/extc++.h>
using namespace __gnu_pbds;

using llt = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;

int const SZ = 2;
using _t = array<llt, SZ>;
const _t MOD = {1000000007LL, 998244353LL};

const _t operator + (const _t & a, const _t & b){
    _t ans;
    for(int i=0;i<SZ;++i){
        ans[i] = (a[i] + b[i]) % MOD[i];
    }
    return ans;
}

const _t operator * (const _t & a, const _t & b){
    _t ans;
    for(int i=0;i<SZ;++i){
        ans[i] = a[i] * b[i] % MOD[i];
    }
    return ans;
}

bool operator == (const _t & a, const _t & b){
    for(int i=0;i<SZ;++i){
        if(a[i] != b[i]) return false;
    }
    return true;
}

int N, M, K;
vvi Board;
vector<vector<_t>> D, U;

int proc(){
    if(1 == Board[1][1] or 1 == Board[N][M]) return 0;

    D.assign(N + 1, vector<_t>(M + 1, {0LL, 0LL}));
    D[1][1] = {1LL, 1LL};
    for(int i=2;i<=M;++i){
        if(0 == Board[1][i]) D[1][i] = D[1][i - 1];
        else break;
    }
    for(int i=2;i<=N;++i){
        if(0 == Board[i][1]) {
            D[i][1] = D[i - 1][1];
        }
        else break;
    }
    for(int i=2;i<=N;++i)for(int j=2;j<=M;++j){
        if(0 == Board[i][j]){
            D[i][j] = D[i - 1][j] + D[i][j - 1];
        }
    }

    U.assign(N + 1, vector<_t>(M + 1, {0LL, 0LL}));
    U[N][M] = {1LL, 1LL};
    for(int i=N-1;i>=1;--i){
        if(0 == Board[i][M]) {
            U[i][M] = U[i + 1][M];
        }
        else break;
    }
    for(int i=M-1;i>=1;--i){
        if(0 == Board[N][i]) U[N][i] = U[N][i + 1];
        else break;
    }
    for(int i=N-1;i>=1;--i)for(int j=M-1;j>=1;--j){
        if(0 == Board[i][j]){
            U[i][j] = U[i + 1][j] + U[i][j + 1];
        }
    }

    assert(U[1][1] == D[N][M]);

    if(0 == D[N][M][0]){
        for(int i=1;i<SZ;++i)assert(0 == D[N][M][i]);
        for(int i=0;i<SZ;++i)assert(0 == U[1][1][i]);
        return 0;
    }    

    for(int i=1;i<=N;++i)for(int j=1;j<=M;++j){
        if(1 == i and 1 == j) continue;
        if(N == i and M == j) continue;
        if(1 == Board[i][j]) continue;
        if(D[i][j] * U[i][j] == D[N][M]){
            return 1;
        }
    }
    return 2;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(0);
    int nofkase = 1;
    // cin >> nofkase;
    while(nofkase--){
        cin >> N >> M >> K;
        Board.assign(N + 1, vi(M + 1, 0));
        for(int x,y,i=0;i<K;++i){
            cin >> x >> y;
            Board[x][y] = 1;
        }
        cout << proc() << endl;
    }
    return 0;
}